A standard way to communicate between two processes A and B (running on the same machine or running on different machines) is to send a message. Often, for example, it is desirable to enable process A to send a message to process B asking process B to execute code on behalf of process A. Typically, process A must have knowledge of a port or contact point for process B in order to do this.
One way to enable process A to call process B is via a remote procedure call (RPC). A remote procedure call enables a process on one computer to cause code to be executed in another process on the same or on a different computer, without requiring explicit code to be written by a developer or programmer to perform that particular call. An RPC is initiated by the caller process (client) sending a request message to a remote system or second process (server) to execute a certain procedure using supplied arguments. A result message is returned to the caller. For example, in a remote procedure call, a function call may be made by process A, in which the name of the procedure that process B is to execute on behalf of process A and a set of parameters for the procedure, are specified. Process B executes the code and returns a message to process A. When the code in question is written using principles of object-oriented programming, RPC is sometimes referred to as remote invocation or remote method invocation.
A remote procedure call typically follows a particular protocol (another way of saying this is “it uses a particular interface”) so that potentially unrelated processes can communicate. The protocol or interface defines the methods and the values which the processes agree upon in order to cooperate.
The procedure of transforming the function call into a message is called marshalling. Marshalling may include gathering data from one or more applications or non-contiguous sources in computer storage, putting the data pieces into a message buffer, and organizing or converting the data into a format that is prescribed for a particular receiver or programming interface. Marshalling typically converts what the code in process A sees as a function call into a message to be sent to process B. The message typically includes the name of the function and a set of parameters, coded in a way that process B understands. Process B receives the message and has to transform the message into a call to process B's internal function. The process of converting a message into a function call is called unmarshalling. The piece of code that performs marshalling in process A is called a proxy and typically resides in the client process. The corresponding piece of code on the server side that performs unmarshalling is called a stub.
Within the context of object oriented programming, process A and process B can be viewed as objects encapsulating data and functions. Some well-known technologies that take this approach are Sun Microsystem's JAVA and Microsoft's COM and DCOM. That is, process B may be viewed as a container for one or multiple objects, whose methods are the functions invoked by process A. In object oriented systems, therefore, process A invokes a method of a particular object of process B instead of invoking a function in process B. To do this, process A must have some way of identifying the object in process B that process A wishes to invoke.
The data stored in process A which enables process A to identify the object of process B is known as a reference to the object. The reference stores information concerning how to locate the object: that is, the reference must be sufficient to identify the process and within the process to identify the object whose method is to be invoked.
It is often helpful for a process to know when no more references to a resource exist. This may be necessary to comply with protocols, for garbage collection (e.g., so that memory resources used to store information associated with the shared resource can be reclaimed, etc.), or for signaling purposes (e.g., so that the execution status of the second process can be determined), or for various other reasons. Reference counting is a technique of storing the number of references, pointers or handles to a resource such as an object or a block of memory. With simple reference counting, whenever a reference is destroyed or overwritten, the reference count of the resource it references is decremented, and whenever a reference is created or copied, the reference count of the resource it references is incremented. When the number of references to a resource reaches zero, the resource is considered to be inaccessible, and is often destroyed. Some methods of reference counting require the process that shares the reference and the process that receives the reference to be actively involved in reference counting and to cooperate with each other. One problem associated with this approach is that it only works when both processes run perfectly: if a process fails or does not complete successfully, the reference count may not be correct. It would be helpful if there were an efficient way to overcome these and other reference counting problems.